/*
数组与切片

数组声明需要指定元素类型及元素个数，语法格式如下：
var variable_name [SIZE] variable_type

声明一个未指定大小的数组来定义切片(slice)
var identifier []type

for range 的坑
*/
package main

import (
	"fmt"
)

func main() {
	arr()

	base()

	// 初始化
	_init()

	// 复制
	_copy()

	// 地址
	addr()

	// for range 的坑
	forRange()

	split()

	share()

	deleteItem()
}

func arr() {
	// 数组，固定长度
	var arr = [6]int{1, 2, 3, 4, 5, 6}
	var avg float32
	// 函数对应的入参也只能是数组，长度保持一致
	avg = getAverage(arr)
	fmt.Printf("平均值为: %f \n", avg)
}

func getAverage(arr [6]int) float32 {
	var i, sum int

	var size = len(arr)

	for i = 0; i < size; i++ {
		sum += arr[i]
	}

	return float32(sum) / float32(size)
}

func _init() {
	fmt.Println("-----初始化-----")
	var nums0 []int
	fmt.Println("nums0", nums0)

	var nums1 = []int{1, 2, 3}
	fmt.Println("nums1", nums1)

	// 指定下标进行初始化
	var nums2 = []int{2: 20, 3: 30}
	fmt.Println("nums2", nums2)
}

func base() {
	// 遍历
	fmt.Println("-----遍历-----")
	var arr = []int{1, 2, 3, 4, 5, 6}
	for i, num := range arr {
		fmt.Println("index:", i, " num:", num)
	}
	fmt.Println("-----遍历-----")

	// 允许对值为 nil 的 slice 添加元素
	var aa []int = nil
	fmt.Println("aa", aa)
	aa = append(aa, 1)
	fmt.Println("aa", aa)

	var numbers = make([]int, 3, 5)
	// len=3 cap=5 slice=[0 0 0]
	fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers), cap(numbers), numbers)

	var nums1 = make([]int, 2, 5)
	// 追加新元素
	nums1 = append(nums1, 10, 11)
	// [0 0 10 11]
	fmt.Println("nums1 ", nums1)
}

func addr() {
	fmt.Println("=====addr=====")
	var nums1 = [3]int{1, 2, 3}
	// 数组不能打印变量位置，只能打印里面元素的位置
	fmt.Printf("addr nums1[0]:%p \n", &nums1[0])
	// 传递数组，会进行数组元素拷贝
	addr1(nums1)

	var nums2 = []int{1, 2, 3}
	fmt.Printf("addr nums2[0]:%p nums:%p \n", &nums2[0], nums2)
	// 切片本质是指针，传递的只是指针的拷贝，不会发生元素拷贝
	addr2(nums2)
}

func addr1(nums [3]int) {
	fmt.Printf("addr1 nums[0]:%p \n", &nums[0])
}

func addr2(nums []int) {
	fmt.Printf("addr2 nums[0]:%p nums:%p \n", &nums[0], &nums)
}

func forRange() {
	fmt.Println("=====for range 的坑=====")
	var nums3 = [5]int{0, 1, 2, 3, 4}
	var nums4 [5]int
	fmt.Println("nums3:", nums3)
	//for i, num := range nums3 {
	for i, num := range &nums3 {
		if i == 1 {
			nums3[2] = 22
		}
		nums4[i] = num
	}
	fmt.Println("nums3:", nums3)
	// range nums3  的情况[0 1 2 3 4]   不符合预期，nums3在range中传递的只是一个副本
	// range &nums3 的情况[0 1 22 3 4]  符合预期
	fmt.Println("nums4:", nums4)

	var nums5 = []int{0, 1, 2, 3, 4}
	var nums6 = make([]int, len(nums5))
	fmt.Println("nums5:", nums5)
	//for i, num := range nums3 {
	for i, num := range nums5 {
		if i == 1 {
			nums5[2] = 22
		}
		nums6[i] = num
	}
	fmt.Println("nums5:", nums5)
	// 切片[0 1 22 3 4] 符合预期
	fmt.Println("nums6:", nums6)
}

func split() {
	fmt.Println("=====split=====")
	var ss = []int{1, 2, 3, 4, 5, 6, 7}
	index := 3

	// 完整语法[low : high : max]，max为最大下标，一般省略第三个参数
	var s1 = ss[:index]
	var s2 = ss[:index:index]
	var s3 = ss[1:index:index]
	fmt.Printf("s0 %v len:%d cap:%d \n", s1, len(s1), cap(s1))
	fmt.Printf("s1 %v len:%d cap:%d \n", s2, len(s2), cap(s2))
	fmt.Printf("s3 %v len:%d cap:%d \n", s3, len(s3), cap(s3))
}

func share() {
	fmt.Println("=====share=====")
	var ss = []int{1, 2, 3, 4, 5, 6, 7}
	index := 3
	fmt.Printf("ss %v len:%d cap:%d [0]:%p [3]%p \n", ss, len(ss), cap(ss), &ss[0], &ss[index])

	var s1 = ss[:index]
	var s2 = ss[index:]
	fmt.Printf("s1 %v len:%d cap:%d [0]:%p \n", s1, len(s1), cap(s1), &s1[0])
	fmt.Printf("s2 %v len:%d cap:%d [0]:%p \n", s2, len(s2), cap(s2), &s2[0])
	fmt.Println(&s2[0] == &ss[index]) // true

	// 不超出原先ss的容量下，底层一直共享
	s1 = append(s1, 10, 11)
	fmt.Println("ss", ss) // [1 2 3 10 11 6 7]
	fmt.Println("s1", s1) // [1 2 3 10 11]
	fmt.Println("s2", s2) // [10 11 6 7]

	s1 = append(s1, 12, 13, 14, 15, 16)
	fmt.Println("ss", ss) // [1 2 3 10 11 6 7]
	fmt.Println("s1", s1) // [1 2 3 10 11 12 13 14 15 16]
	fmt.Println("s2", s2) // [10 11 6 7]
}

func _copy() {
	fmt.Println("=====copy=====")
	var nums1 = []int{1, 2, 3}
	var nums2 = make([]int, len(nums1), cap(nums1))
	fmt.Printf("nums1[0]:%p nums2[0]:%p \n", &nums1[0], &nums2[0])
	copy(nums2, nums1)
	fmt.Printf("nums1[0]:%p nums2[0]:%p \n", &nums1[0], &nums2[0])
	copy(nums2, nums1)
	fmt.Printf("nums1[0]:%p nums2[0]:%p \n", &nums1[0], &nums2[0])
	fmt.Println("nums2 ", nums2)
}

func deleteItem() {
	fmt.Println("=====删除元素=====")
	arr := []int{0, 1, 2}
	fmt.Println("arr", arr)
	i := 0
	arr = append(arr[0:i], arr[i+1:]...)
	fmt.Println("arr", arr)

	arr = []int{0, 1, 2}
	fmt.Println("arr", arr)
	i = 1
	arr = append(arr[0:i], arr[i+1:]...)
	fmt.Println("arr", arr)

	arr = []int{0, 1, 2}
	fmt.Println("arr", arr)
	i = 2
	arr = append(arr[0:i], arr[i+1:]...)
	fmt.Println("arr", arr)
}
